using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using Castle.DynamicProxy;
using Legend.Fakes.Extensibility;
using System.ComponentModel;
using Legend.Fakes.Api;

namespace Legend.Fakes
{
    /// <summary>
    /// Provides methods for generating fake objects.
    /// </summary>
    public static class A
    {
        private static ProxyGenerator proxyGenerator = new ProxyGenerator();

        /// <summary>
        /// Creates a fake object of the type T.
        /// </summary>
        /// <typeparam name="T">The type of fake object to create.</typeparam>
        /// <returns>A fake object.</returns>
        public static T Fake<T>() where T : class
        {
            var fake = new FakeObject(typeof(T));
            return (T)fake.Object;
        }

        /// <summary>
        /// Creates a fake object of the non interface type T.
        /// </summary>
        /// <typeparam name="T">The type of fake object to create.</typeparam>
        /// <param name="constructorCall">An expression that specifies the parameters that will
        /// be passed to the constructor of the generated fake class.</param>
        /// <returns>A fake object.</returns>
        public static T Fake<T>(Expression<Func<T>> constructorCall) where T : class
        {
            Guard.IsNotNull(constructorCall, "constructorCall");

            if (constructorCall.Body.NodeType != ExpressionType.New)
            {
                throw new ArgumentException(ExceptionMessages.NonConstructorExpressionMessage);
            }

            var constructorArguments =
                (from argument in ((NewExpression)constructorCall.Body).Arguments
                 select ExpressionManager.GetValueProducedByExpression(argument)).ToArray();

            return (T)new FakeObject(typeof(T), constructorArguments).Object;
        }

        

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static bool Equals(object a, object b)
        {
            return object.Equals(a, b);
        }

        [EditorBrowsable(EditorBrowsableState.Never)]
        public static bool ReferenceEquals(object a, object b)
        {
            return object.ReferenceEquals(a, b);
        }
    }
}